package com.xiaoh.dormitoryrepairreportbackend.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaoh.dormitoryrepairreportbackend.annotation.RequireRole;
import com.xiaoh.dormitoryrepairreportbackend.common.BaseResponse;
import com.xiaoh.dormitoryrepairreportbackend.common.ErrorCode;
import com.xiaoh.dormitoryrepairreportbackend.constant.UserConstant;
import com.xiaoh.dormitoryrepairreportbackend.exception.BusinessException;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.common.PageResponse;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.common.UpdateRequest;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.material.MaterialAddRequest;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.material.MaterialQueryRequest;
import com.xiaoh.dormitoryrepairreportbackend.model.dto.material.MaterialUpdateRequest;
import com.xiaoh.dormitoryrepairreportbackend.model.entity.Material;
import com.xiaoh.dormitoryrepairreportbackend.service.MaterialService;
import com.xiaoh.dormitoryrepairreportbackend.utils.QueryUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 物料接口
 */
@RestController
@RequestMapping("/material")
@Slf4j
@Tag(name = "物料管理", description = "物料相关接口")
public class MaterialController {

    @Resource
    private MaterialService materialService;

    private static final Integer WARMING_THRESHOLD = 10;

    /**
     * 创建物料
     */
    @PostMapping("/add")
    @Operation(summary = "创建物料", description = "创建物料接口")
    @RequireRole(UserConstant.UserType.ADMIN)
    public BaseResponse<Long> addMaterial(@Valid @RequestBody MaterialAddRequest materialAddRequest, HttpServletRequest request) {
        if (materialAddRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Material material = new Material();
        BeanUtils.copyProperties(materialAddRequest, material);

        boolean result = materialService.save(material);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return BaseResponse.success(material.getId().longValue());
    }

    /**
     * 更新物料
     */
    @PostMapping("/update")
    @Operation(summary = "更新物料", description = "更新物料接口")
    @RequireRole(UserConstant.UserType.ADMIN)
    public BaseResponse<Boolean> updateMaterial(@Valid @RequestBody MaterialUpdateRequest materialUpdateRequest, HttpServletRequest request) {
        if (materialUpdateRequest == null || materialUpdateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        Integer id = materialUpdateRequest.getId();
        // 校验数据是否存在
        Material oldMaterial = materialService.getById(id);
        if (oldMaterial == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        Material material = new Material();
        BeanUtils.copyProperties(materialUpdateRequest, material);

        boolean result = materialService.updateById(material);
        if (!result) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return BaseResponse.success(true);
    }

    /**
     * 删除物料
     */
    @PostMapping("/delete")
    @Operation(summary = "删除物料", description = "删除物料接口")
    @RequireRole(UserConstant.UserType.ADMIN)
    public BaseResponse<Boolean> deleteMaterial(@Valid @RequestBody UpdateRequest updateRequest, HttpServletRequest request) {
        if (updateRequest == null || updateRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        long id = updateRequest.getId();
        // 校验数据是否存在
        Material oldMaterial = materialService.getById(id);
        if (oldMaterial == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        boolean b = materialService.removeById(id);
        return BaseResponse.success(b);
    }

    /**
     * 根据 id 获取物料
     */
    @PostMapping("/get")
    @Operation(summary = "根据id获取物料", description = "根据id获取物料")
    public BaseResponse<Material> getMaterialById(@Valid @RequestBody UpdateRequest getRequest) {
        if (getRequest == null || getRequest.getId() == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long id = getRequest.getId();
        Material material = materialService.getById(id);
        if (material == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        return BaseResponse.success(material);
    }

    /**
     * 分页获取物料列表
     * 使用游标分页保持性能，同时返回完整分页信息
     */
    @PostMapping("/list/page")
    @Operation(summary = "分页获取物料列表", description = "使用游标分页获取物料列表，返回完整分页信息（总记录数、总页数等）")
    @RequireRole({UserConstant.UserType.ADMIN, UserConstant.UserType.MAINTENANCE})
    public BaseResponse<PageResponse<Material>> listMaterialByPage(@RequestBody MaterialQueryRequest materialQueryRequest) {
        if (materialQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        QueryWrapper<Material> queryWrapper = new QueryWrapper<>();

        // 添加查询条件
        QueryUtils.addLikeCondition(queryWrapper, "name", materialQueryRequest.getName());
        QueryUtils.addLikeCondition(queryWrapper, "model", materialQueryRequest.getModel());
        QueryUtils.addEqCondition(queryWrapper, "unit", materialQueryRequest.getUnit());

        // 库存不足 或者 只要存储足
        if (materialQueryRequest.getIsLowStock() != null) {
            if (materialQueryRequest.getIsLowStock()) {
                // 查询同一列数据中的两个字段的值 库存数量 <= 预警值
                queryWrapper.apply("stock_count <= warning_threshold");
            }else {
                queryWrapper.apply("stock_count > warning_threshold");
            }
        }

        // 查询总记录数（不包含分页条件）
        QueryWrapper<Material> countWrapper = QueryUtils.createCountQueryWrapper(queryWrapper);
        Long total = materialService.count(countWrapper);

        // 添加游标分页
        QueryUtils.addCursorPagination(queryWrapper, materialQueryRequest.getLastId(), materialQueryRequest.getPageSize());

        // 查询物料列表
        List<Material> materialList = materialService.list(queryWrapper);

        // 获取下一页游标
        Long nextCursor = QueryUtils.getNextCursor(materialList);

        // 计算当前页码
        Long current = QueryUtils.calculateCurrentPage(materialQueryRequest.getLastId(), materialQueryRequest.getPageSize(), total);

        // 构建分页响应
        PageResponse<Material> pageResponse = PageResponse.of(materialList, current, materialQueryRequest.getPageSize().longValue(), total, nextCursor);
        return BaseResponse.success(pageResponse);
    }

    /**
     * 获取库存预警物料
     */
    @PostMapping("/list/warning")
    @Operation(summary = "获取库存预警物料", description = "获取库存不足的物料列表")
    @RequireRole({UserConstant.UserType.ADMIN, UserConstant.UserType.MAINTENANCE})
    public BaseResponse<List<Material>> listWarningMaterial() {
        QueryWrapper<Material> queryWrapper = new QueryWrapper<>();
        // 库存数量 <= 预警值
        queryWrapper.le("stock_count", WARMING_THRESHOLD);
        queryWrapper.orderByAsc("stock_count");

        List<Material> materialList = materialService.list(queryWrapper);
        return BaseResponse.success(materialList);
    }
}
